package com.dahua.messageconsumer.sqlmq;

import com.alibaba.fastjson.JSON;
import com.dahua.common.CommonMethod;
import com.dahua.common.GsonUtils;
import com.dahua.common.config.LatestSensorStatusData;
import com.dahua.common.config.PublicVars;
import com.dahua.common.config.PublicVarsTimeDay;
import com.dahua.common.dao.*;
import com.dahua.common.domain.*;
import com.dahua.common.manager.SensorDataManager;
import com.dahua.messageconsumer.model.EmailData;
import com.dahua.messageconsumer.model.EmailDatalList;
import com.dahua.messageconsumer.service.ActiveMqConfig;
import com.dahua.messageconsumer.sql.*;
import com.google.gson.reflect.TypeToken;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.jms.*;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

@Slf4j
@Data
public class Consumer implements Runnable {

    public Consumer(String dataType, Integer threadid, Integer sqltrytimes, ActiveMqConfig activeMqConfig,String websocket3,
                    SensorDataManager sensorDataManager,
                    SensorDataDhMapper sensorDataDhMapper,
                    ElevatorMapper elevatorMapper,
                    LatestEquipmentStatusDao latestEquipmentStatusDao,
                    Control56Mapper control56Mapper,
                    EquipmentStatusMapper equipmentStatusMapper,
                    EquipmentStatusThisMonthMapper equipmentStatusThisMonthMapper,
                    EquipmentStatusTodayMapper equipmentStatusTodayMapper,
                    EquipmentStatusAlldayMapper equipmentStatusAlldayMapper,
                    DataLogMapper dataLogMapper,
                    LatestFaultMapper latestFaultMapper,
                    RuntimeParamMapper runtimeParamMapper,
                    FaultallMapper faultallMapper,
                    EquipmentFaultMapper equipmentFaultMapper,
                    EquipmentFaultDhMapper equipmentFaultDhMapper,
                    FaultMapper faultMapper,
                    SyncMessageMapper syncMessageMapper,
                    VersionInfoDao versionInfoDao,
                    ClientConfigparamsVersionUploadDao clientConfigparamsVersionUploadDao,
                    ClientConfigsUploadDao clientConfigsUploadDao,
                    ClientParamsUploadDao clientParamsUploadDao,
                    ClientAiParamsUploadDao clientAiParamsUploadDao,
                    ClientVibParamsUploadDao clientVibParamsUploadDao,
                    ClientPublicParamsUploadDao clientPublicParamsUploadDao,
                    ClientDmParamsUploadDao clientDmParamsUploadDao,
                    ClientAiVibPublicDmUploadTimeDao clientAiVibPublicDmUploadTimeDao,
                    EquipmentMapper equipmentMapper,
                    FaultInfoMapper faultInfoMapper
                    ) {
        this.dataType = dataType;
        this.threadid = threadid;
        this.queue = String.format("%s_%d", this.dataType, this.threadid);
        this.activeMqConfig = activeMqConfig;
        this.sqltrytimes = sqltrytimes;
        this.websocket3 = websocket3;

        this.sensorDataManager = sensorDataManager;
        this.sensorDataDhMapper = sensorDataDhMapper;
        this.elevatorMapper = elevatorMapper;
        this.latestEquipmentStatusDao = latestEquipmentStatusDao;
        this.control56Mapper = control56Mapper;

        this.equipmentStatusMapper = equipmentStatusMapper;
        this.equipmentStatusThisMonthMapper = equipmentStatusThisMonthMapper;
        this.equipmentStatusTodayMapper = equipmentStatusTodayMapper;
        this.equipmentStatusAlldayMapper = equipmentStatusAlldayMapper;

        this.dataLogMapper = dataLogMapper;
        this.latestFaultMapper = latestFaultMapper;
        this.runtimeParamMapper = runtimeParamMapper;

        this.faultallMapper = faultallMapper;
        this.equipmentFaultMapper = equipmentFaultMapper;
        this.equipmentFaultDhMapper = equipmentFaultDhMapper;

        this.faultMapper = faultMapper;
        this.syncMessageMapper = syncMessageMapper;

        this.versionInfoDao = versionInfoDao;

        this.clientConfigparamsVersionUploadDao = clientConfigparamsVersionUploadDao;
        this.clientConfigsUploadDao = clientConfigsUploadDao;
        this.clientParamsUploadDao = clientParamsUploadDao;
        this.clientAiParamsUploadDao = clientAiParamsUploadDao;
        this.clientVibParamsUploadDao = clientVibParamsUploadDao;
        this.clientPublicParamsUploadDao = clientPublicParamsUploadDao;
        this.clientDmParamsUploadDao = clientDmParamsUploadDao;
        this.clientAiVibPublicDmUploadTimeDao = clientAiVibPublicDmUploadTimeDao;

        this.equipmentMapper = equipmentMapper;
        this.faultInfoMapper = faultInfoMapper;

        log.info(this.queue);
    }

    private String dataType;
    private Integer threadid;
    private String queue;
    private ActiveMqConfig activeMqConfig;
    private Integer sqltrytimes;
    private String websocket3;

    private SensorDataManager sensorDataManager;
    private SensorDataDhMapper sensorDataDhMapper;
    private ElevatorMapper elevatorMapper;
    private LatestEquipmentStatusDao latestEquipmentStatusDao;
    private Control56Mapper control56Mapper;
    private EquipmentStatusMapper equipmentStatusMapper;
    private EquipmentStatusThisMonthMapper equipmentStatusThisMonthMapper;
    private EquipmentStatusTodayMapper equipmentStatusTodayMapper;
    private EquipmentStatusAlldayMapper equipmentStatusAlldayMapper;
    private DataLogMapper dataLogMapper;
    private LatestFaultMapper latestFaultMapper;
    private RuntimeParamMapper runtimeParamMapper;
    private FaultallMapper faultallMapper;
    private EquipmentFaultMapper equipmentFaultMapper;
    private EquipmentFaultDhMapper equipmentFaultDhMapper;
    private SyncMessageMapper syncMessageMapper;

    private FaultMapper faultMapper;
    private VersionInfoDao versionInfoDao;
    private ClientConfigparamsVersionUploadDao clientConfigparamsVersionUploadDao;
    private ClientConfigsUploadDao clientConfigsUploadDao;
    private ClientParamsUploadDao clientParamsUploadDao;
    private ClientAiParamsUploadDao clientAiParamsUploadDao;
    private ClientVibParamsUploadDao clientVibParamsUploadDao;
    private ClientPublicParamsUploadDao clientPublicParamsUploadDao;
    private ClientDmParamsUploadDao clientDmParamsUploadDao;
    private ClientAiVibPublicDmUploadTimeDao clientAiVibPublicDmUploadTimeDao;

    private EquipmentMapper equipmentMapper;
    private FaultInfoMapper faultInfoMapper;

    @Override
    public void run() {
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(activeMqConfig.getUrl(), activeMqConfig.getUser(), activeMqConfig.getPassword());

        Connection connection = null;
        Session session = null;
        MessageConsumer messageConsumer = null;

        int logcount = 0;

        while(true) {
            try {
                if (Thread.currentThread().isInterrupted()) {
                    break;
                }

                if (connection == null) {
                    connection = connectionFactory.createConnection();
                    connection.start();
                }

                if (messageConsumer == null) {
                    session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                    Queue q = session.createQueue(this.queue);
                    messageConsumer = session.createConsumer(q);
                }

                if (logcount == 0) {
                    log.info("等待接收消息...");
                }
                Message message = messageConsumer.receive();
                if (message == null) {
                    continue;
                }
                if (logcount == 0) {
                    log.info("收到消息1条");
                }

                logcount++;
                if (logcount > 100000) {
                    logcount = 0;
                }

                if (message instanceof TextMessage) {
                    TextMessage objectMessage = (TextMessage) message;
                    sqlProcess(objectMessage.getText());
                }
                //                message.acknowledge();
            } catch (Throwable e) {
                e.printStackTrace();

                if (e instanceof JMSException) {
                    closeQuietly(connection);
                    connection = null;
                    session = null;
                    messageConsumer = null;
                }

                try {
                    log.info("出错等待5秒后重试");
                    Thread.sleep(5000);
                } catch (InterruptedException ex) {
                    break;
                }
            }
        }

        closeQuietly(connection);
        log.info("线程退出");
    }

    private void closeQuietly(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (Throwable e) {
                // do nothing
            }
        }
    }
    private void sqlProcess(String sqlData) {
        DataTypeAndContent  dataTypeAndContent = JSON.parseObject(sqlData, DataTypeAndContent.class);

        if (dataTypeAndContent == null) {
            log.error("dataTypeAndContent = null");
            return;
        }
        switch (dataTypeAndContent.getDataType()) {
            case SQLDataType.SENSOR_DATA: {
                QueueTimes.mqSensorDataP1();
                saveSensorData(dataTypeAndContent.getSensorData(), SQLDataType.SENSOR_DATA_ACTION);
                break;
            }
            case SQLDataType.EQUIPMENT_STATUS: {
                QueueTimes.mqDataP1();
                saveEquipmentStatus(dataTypeAndContent.getEquipmentStatus(), SQLDataType.EQUIPMENT_STATUS_ACTION);
                break;
            }
            case SQLDataType.SENSOR_DATA_DH: {
                saveSensorDataDh(dataTypeAndContent.getSensorData(), SQLDataType.EQUIPMENT_STATUS_ACTION);
                break;
            }
            case SQLDataType.CONTROL56: {
                QueueTimes.mq56P1();
                control56(dataTypeAndContent.getControl56(), SQLDataType.CONTROL56_ACTION);
                break;
            }
            case SQLDataType.ELEVATOR: {
                QueueTimes.mq56zP1();
                elevator(dataTypeAndContent.getElevator(), SQLDataType.ELEVATOR_ACTION);
                break;
            }
            case SQLDataType.LATEST_EQUIPMENT_STATUS: {
                latestEquipmentStatus(dataTypeAndContent.getEquipmentStatus(), SQLDataType.LATEST_EQUIPMENT_STATUS_ACTION);
                break;
            }
            case SQLDataType.UPLOAD_STATUS: {
                uploadStatus(dataTypeAndContent.getUploadStatus(), SQLDataType.UPLOAD_STATUS_ACTION);
                break;
            }
            case SQLDataType.DATA_LOG: {
                dataLog(dataTypeAndContent.getDataLog(), SQLDataType.DATA_LOG_ACTION);
                break;
            }
            case SQLDataType.LATEST_FAULT_INSERT_UPDATE: {
                latestFaultInsertUpdate(dataTypeAndContent.getFault(), SQLDataType.LATEST_FAULT_INSERT_UPDATE_ACTION);
                break;
            }
            case SQLDataType.LATEST_FAULT_DELETE: {
                latestFaultDelete(dataTypeAndContent.getLatestFaultDeleteId(), SQLDataType.LATEST_FAULT_DELETE_ACTION);
                break;
            }
            case SQLDataType.REPORT_NODATA: {
                reportNoData(dataTypeAndContent.getReportNoData(), SQLDataType.REPORT_NODATA_ACTION);
                break;
            }
            case SQLDataType.EQUIPMENT_FAULT: {
                equipmentFault(dataTypeAndContent.getFaultall(), SQLDataType.EQUIPMENT_FAULT_ACTION);
                break;
            }
            case SQLDataType.EQUIPMENT_FAULT_DH: {
                equipmentFaultDh(dataTypeAndContent.getFaultall(), SQLDataType.EQUIPMENT_FAULT_DH_ACTION);
                break;
            }
            case SQLDataType.FAULT_ALL_INSERT: {
                faultall(dataTypeAndContent.getFaultall(), SQLDataType.EQUIPMENT_FAULT_ACTION, true);
                break;
            }
            case SQLDataType.FAULT_ALL_UPDATE: {
                faultall(dataTypeAndContent.getFaultall(), SQLDataType.EQUIPMENT_FAULT_ACTION, false);
                break;
            }
            case SQLDataType.SAVE_FAULT_SYNC: {
                if (dataTypeAndContent.getSaveFaultData() == null) {
                    break;
                }
                faultAndAllAndSync(dataTypeAndContent.getSaveFaultData().getFault(), SQLDataType.SAVE_FAULT_SYNC_ACTION, dataTypeAndContent.getSaveFaultData().getSampleseconds());
                break;
            }
            case SQLDataType.SAVE_FAULT_UPDATE_SYNC: {
                if (dataTypeAndContent.getSaveFaultData() == null) {
                    break;
                }
                faultAndAllAndSyncAndUpdate(dataTypeAndContent.getSaveFaultData().getLastFault(),dataTypeAndContent.getSaveFaultData().getFault(), dataTypeAndContent.getSaveFaultData().getSampleseconds(), SQLDataType.SAVE_FAULT_SYNC_ACTION);
                break;
            }
            case SQLDataType.SAVE_FAULT_56: {
                if (dataTypeAndContent.getSaveFaultData() == null) {
                    break;
                }
                faultAndAllAndSync56(dataTypeAndContent.getSaveFaultData().getFault(), SQLDataType.SAVE_FAULT_56_ACTION, dataTypeAndContent.getSaveFaultData().getSampleseconds());
                break;
            }
            case SQLDataType.SAVE_FAULT_ELEVATOR: {
                if (dataTypeAndContent.getSaveFaultData() == null) {
                    break;
                }
                fault4ElevatorAndSync(dataTypeAndContent.getSaveFaultData().getFault(), SQLDataType.SAVE_FAULT_ELEVATOR_ACTION, dataTypeAndContent.getSaveFaultData().getSampleseconds());
                break;
            }
            case SQLDataType.UPLOAD_CONFIGS: {
                QueueTimes.mqUploadP1();
                if (StringUtils.isEmpty(dataTypeAndContent.getData())) {
                    break;
                }
                uploadConfigs(dataTypeAndContent.getData());
                break;
            }
            default: {
                log.error("dataTypeAndContent invalid {} - {}", sqlData);
            }
        }
    }

    private void uploadStatus(UploadStatus uploadStatus, String action) {
        if (uploadStatus == null) {
            log.error("uploadStatus == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                this.sensorDataManager.updateUploadStatus(uploadStatus.getEquipmentId(), uploadStatus.getSensorId(), uploadStatus.getTime());
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            QueueTimes.tryUpload++;
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    private void elevator(Elevator elevator, String action) {
        if (elevator == null) {
            log.error("elevator == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                this.elevatorMapper.insert(elevator);
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            QueueTimes.try56z++;
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    private void latestEquipmentStatus(EquipmentStatus equipmentStatus, String action) {
        if (equipmentStatus == null) {
            log.error("equipmentStatus == null");
            return;
        }
        // 第一次从数据库获取B类故障（例如中间服务重启）
        if (!LatestSensorStatusData.hasControl56Fault.containsKey(equipmentStatus.getEq_ID())) {
            List<Fault> fb = latestFaultMapper.selectLatestBFaultByEqId(equipmentStatus.getEq_ID());
            if (fb == null || fb.isEmpty()) {
                LatestSensorStatusData.hasControl56Fault.put(equipmentStatus.getEq_ID(), 0);
                LatestSensorStatusData.latest56Fault.remove(equipmentStatus.getEq_ID());
            } else {
                LatestSensorStatusData.hasControl56Fault.put(equipmentStatus.getEq_ID(), 1);
                LatestSensorStatusData.latest56Fault.put(equipmentStatus.getEq_ID(), fb.get(0));
            }
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                EquipmentStatus lastEquipmentStatus = LatestSensorStatusData.latestEquipmentStatuses.get(equipmentStatus.getEq_ID());
                if (lastEquipmentStatus == null) {
                    // 需要加载
                    lastEquipmentStatus = latestEquipmentStatusDao.selectByEqId(equipmentStatus.getEq_ID());
                }

                // 比较与合并 lastEquipmentStatus + equipmentStatus
                LatestSensorStatusData.merge(equipmentStatus, lastEquipmentStatus, control56Mapper, PublicVars.getEquipment(equipmentMapper, equipmentStatus.getEq_ID()), faultInfoMapper);
                // 如果是来自 control56，并且状态是0，则不需要记录 SyncTime了。
                if (equipmentStatus.getSyncTime() != null && equipmentStatus.getStatus().equals(0)) {
                    equipmentStatus.setSyncTime(null);
                }
                if (equipmentStatus.getDataServerId() == null) {
                    equipmentStatus.setDataServerId(0);
                }
                if (equipmentStatus.getBk2id() == null) {
                    equipmentStatus.setBk2id((long)LatestSensorStatusData.BJNONE);
                }

                // B类故障，这个就一直保持故障。用于计算故障时间。
                if ( !com.dahua.messageconsumer.MessageConsumer.isMaintainenceStatus.containsKey(equipmentStatus.getEq_ID())
                        && LatestSensorStatusData.hasControl56Fault.containsKey(equipmentStatus.getEq_ID())
                        && LatestSensorStatusData.hasControl56Fault.get(equipmentStatus.getEq_ID()) > 0
                ) {
                    equipmentStatus.setStatus(3);
                }
                if (latestEquipmentStatusDao.update(equipmentStatus) <= 0) {
                    latestEquipmentStatusDao.insert(equipmentStatus);
                }
                LatestSensorStatusData.latestEquipmentStatuses.put(equipmentStatus.getEq_ID(), equipmentStatus);
                break;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
        // 如果有B类最新故障

    }

    private void control56(Control56 control56, String action) {
        if (control56 == null) {
            log.error("control56 == null");
            return;
        }
        for (int i = 0; i < sqltrytimes; i++) {
            try {
                control56Mapper.insert(control56);
                break;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            QueueTimes.try56++;
            try {
                Thread.sleep(2000);
            } catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
        // 如果是维保状态，清理B类最新故障
        // 清理B类最新故障
        if (LatestSensorStatusData.hasControl56Fault.containsKey(control56.getEquipmentid())
                && LatestSensorStatusData.hasControl56Fault.get(control56.getEquipmentid()) == 0
        ) {
            for (int i = 0; i < sqltrytimes; i++) {
                try {
                    latestFaultMapper.deleteLatestBFaultByEqIdAndId(control56.getEquipmentid());
                    break;
                } catch (Exception ex) {
                    log.error("{} error: {}", action, ex.getMessage());
                }
                // 隔2秒再试
                QueueTimes.try56++;
                try {
                    Thread.sleep(2000);
                } catch (Exception ex2) {
                    log.error("{} sleep error: {}", action, ex2.getMessage());
                }
            }
        }
    }

    private void saveEquipmentStatus(EquipmentStatus equipmentStatus, String action) {
        if (equipmentStatus == null) {
            log.error("equipmentStatus == null");
            return;
        }

        // B类故障，这个就一直保持故障。用于计算故障时间。
        if ( !com.dahua.messageconsumer.MessageConsumer.isMaintainenceStatus.containsKey(equipmentStatus.getEq_ID())
                && LatestSensorStatusData.hasControl56Fault.containsKey(equipmentStatus.getEq_ID())
                && LatestSensorStatusData.hasControl56Fault.get(equipmentStatus.getEq_ID()) > 0
        ) {
            equipmentStatus.setStatus(3);
        }

        saveEquipmentStatusThisMonth(equipmentStatus);

        EquipmentStatus lastEquipmentStatus = equipmentStatusMapper.getLastEquipmentStatus(equipmentStatus.getEq_ID());
        if (lastEquipmentStatus != null) {
            // 4 等同于0，为了方便统计和减少记录数量，如果是4，按 0 写入
            // 5 和其他一样单独统计，由于5是停机状态，长期停机只传输前几条记录，因此 ： 停机时间不能靠5的合计时间。

            boolean statusEqual = lastEquipmentStatus.getStatus().equals(equipmentStatus.getStatus());
            if (statusEqual && isSameDate(lastEquipmentStatus.getTime(), equipmentStatus.getTime())) {
                //int period = (int) Duration.between(lastEquipmentStatus.getTime(), equipmentStatus.getTime()).toMinutes();
                int period = lastEquipmentStatus.getPeriod() + equipmentStatus.getPeriod(); // PublicVars.sampleseconds; // 改为秒
                for (int i = 0; i< sqltrytimes; i++) {
                    try {
                        equipmentStatusMapper.updateEndTimeAndPeriodAndTotalTimes(equipmentStatus.getTime(), period, lastEquipmentStatus.getTotalTimes() + 1, lastEquipmentStatus.getID());
                        return;
                    } catch (Exception ex) {
                        log.error("{} error: {}", action, ex.getMessage());
                    }
                    // 隔2秒再试
                    QueueTimes.tryData++;
                    try {
                        Thread.sleep(2000);
                    }catch (Exception ex2) {
                        log.error("{} sleep error: {}", action, ex2.getMessage());
                    }
                }
            }
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                equipmentStatusMapper.insert(equipmentStatus);;
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            QueueTimes.tryData++;
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    private void saveEquipmentStatusThisMonth(EquipmentStatus equipmentStatus) {
        // 后面非当月的通过后台JOB处理
        // 4 等同于0，为了方便统计和减少记录数量，如果是4，按 0 写入
        if(equipmentStatus.getStatus() == 4) {
            equipmentStatus.setStatus(0);
        }

        // 线路无需记录。
        if (PublicVars.isPortalWithData == 0 || equipmentStatus.getPeriod() <= 0) {
            return;
        }
        //equipmentStatus.setYyyymm(equipmentStatus.getTime().getYear()*100 + equipmentStatus.getTime().getMonthValue());
        //equipmentStatus.setYyyymmdd(equipmentStatus.getTime().getYear()*10000 + equipmentStatus.getTime().getMonthValue()*100 + equipmentStatus.getTime().getDayOfMonth());
        // HongKong 改为根据配置
        equipmentStatus.setYyyymm(PublicVarsTimeDay.getYyyymm(equipmentStatus.getTime()));
        equipmentStatus.setYyyymmdd(PublicVarsTimeDay.getYyyymmdd(equipmentStatus.getTime()));

        // 这几个暂时不try-catch了，失败几次影响不大
        if (equipmentStatusThisMonthMapper.updateEndTimeAndPeriodAndTotalTimes(equipmentStatus.getEq_ID(),equipmentStatus.getYyyymm(),equipmentStatus.getStatus(),equipmentStatus.getPeriod()) <= 0)
            equipmentStatusThisMonthMapper.insert(equipmentStatus);

        // 如果不是当天就不用更新了（例如通讯中断后补发的）
        // if (equipmentStatus.getTime().isAfter(LocalDateTime.of(LocalDate.now(), LocalTime.MIN))) {
        if (PublicVarsTimeDay.isToday(equipmentStatus.getTime())) {
            if (equipmentStatusTodayMapper.updateEndTimeAndPeriodAndTotalTimes(equipmentStatus.getEq_ID(), equipmentStatus.getYyyymmdd(), equipmentStatus.getStatus(), equipmentStatus.getPeriod()) <= 0)
                equipmentStatusTodayMapper.insert(equipmentStatus);
        }

        if (equipmentStatusAlldayMapper.updateEndTimeAndPeriodAndTotalTimes(equipmentStatus.getEq_ID(),equipmentStatus.getYyyymmdd(),equipmentStatus.getStatus(),equipmentStatus.getPeriod()) <= 0)
            equipmentStatusAlldayMapper.insert(equipmentStatus);

    }
    private boolean isSameDate(LocalDateTime d1, LocalDateTime d2) {
        return d1.getYear() == d2.getYear() && d1.getMonthValue() == d2.getMonthValue() && d1.getDayOfMonth() == d2.getDayOfMonth();
    }

    private void dataLog(DataLog dataLog, String action) {
        if (dataLog == null) {
            log.error("dataLog == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                if (dataLogMapper.update(dataLog) <= 0) {
                    dataLogMapper.insert(dataLog);
                }
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    private void latestFaultInsertUpdate(Fault fault, String action) {
        if (fault == null) {
            log.error("fault == null");
            return;
        }
        // 目前只有A类发到这里。
        if (!LatestSensorStatusData.hasControl56Fault.containsKey(fault.getEq_ID())) {
            List<Fault> fb = latestFaultMapper.selectLatestBFaultByEqId(fault.getEq_ID());
            if (fb == null || fb.isEmpty()) {
                LatestSensorStatusData.hasControl56Fault.put(fault.getEq_ID(), 0);
                LatestSensorStatusData.latest56Fault.remove(fault.getEq_ID());
            } else {
                LatestSensorStatusData.hasControl56Fault.put(fault.getEq_ID(), 1);
                LatestSensorStatusData.latest56Fault.put(fault.getEq_ID(), fb.get(0));
            }
        } // B 类优先 。
        if (LatestSensorStatusData.hasControl56Fault.get(fault.getEq_ID()) > 0) {
            return;
        }

        for (int i = 0; i< sqltrytimes; i++) {
            try {
                if (latestFaultMapper.updateLatestFault(fault) <= 0) {
                    latestFaultMapper.insertLatestFault(fault);
                }
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }
    private void latestFaultDelete(LatestFaultDeleteId latestFaultDeleteId, String action) {
        if (latestFaultDeleteId == null) {
            log.error("latestFaultDeleteId == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                latestFaultMapper.deleteLatestFaultByEqIdAndId(latestFaultDeleteId.getEqId(), latestFaultDeleteId.getId());
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    private void saveSensorData(SensorData sensorData, String action) {
        if (sensorData == null) {
            log.error("sensorData == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                sensorDataManager.saveSensorData(sensorData);
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            QueueTimes.trySensorData++;
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    private void saveSensorDataDh(SensorData sensorData, String action) {
        if (sensorData == null) {
            log.error("sensorData == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                sensorDataDhMapper.insert(sensorData);
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    // 增加 没有数据时间，方便了解工控机的状态（没有数据的时候断网？有数据没传？没有数据产生？）
    public void reportNoData(ReportNoData reportNoData, String action) {
        if (reportNoData == null) {
            log.error("reportNoData == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                sensorDataManager.reportNoData(reportNoData.getEquipmentId(), reportNoData.getReporttime());
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    public void equipmentFault(Faultall faultall, String action) {
        QueueTimes.mqEquipmentFaultP1();
        if (faultall == null) {
            log.error("faultall == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                int ret = equipmentFaultMapper.update(faultall);
                if (ret == 0) {
                    equipmentFaultMapper.insert(faultall);
                }
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            QueueTimes.tryEquipmentFault++;
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    public void equipmentFaultDh(Faultall faultall, String action) {
        QueueTimes.mqEquipmentFault_dhP1();
        if (faultall == null) {
            log.error("faultall == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                int ret = equipmentFaultDhMapper.update(faultall);
                if (ret == 0) {
                    equipmentFaultDhMapper.insert(faultall);
                }
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            QueueTimes.tryEquipmentFault_dh++;
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    public void faultall(Faultall faultall, String action, boolean isInsert) {
        if (faultall == null) {
            log.error("faultall == null");
            return;
        }
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                if (isInsert) {
                    faultallMapper.insert(faultall);
                } else {
                    faultallMapper.updateByIdSync(faultall);
                }
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
    }

    public void faultAndAllAndSync(Fault fault, String action, int sampleseconds) {
        if (fault == null) {
            log.error("fault == null");
            return;
        }
        /* 后面需要用到 faultId，需要放在一起处理
                //已经配置返回 id
                faultMapper.insert(fault);

                fault.setBk3id(fault.getID());
                faultMapper.updateBk3id(fault.getBk3id(),fault.getID());

                publishFault(fault);

                saveFaultall(fault,false, sampleseconds);
                createWorkbillIfNeed(fault);
         */
        boolean lastAction = false;
        for (int i = 0; i < sqltrytimes; i++) {
            try {
                //已经配置返回 id
                faultMapper.insert(fault);
                lastAction = true;
                break;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
        if (!lastAction) {
            return;
        }

        lastAction = false;
        fault.setBk3id(fault.getID());
        for (int i = 0; i < sqltrytimes; i++) {
            try {
                //已经配置返回 id
                faultMapper.updateBk3id(fault.getBk3id(),fault.getID());
                lastAction = true;
                break;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
        if (!lastAction) {
            return;
        }


        publishFault(fault);

        saveFaultall(fault,false, sampleseconds);
        createWorkbillIfNeed(fault);
    }
    private void publishFault(Fault fault) {
        // 故障转发邮件
        if (!StringUtils.isEmpty(websocket3) && "A".equalsIgnoreCase(fault.getSensortype())) {
            EmailData emailData = new EmailData();
            emailData.setDataType(1);
            emailData.setEqId(fault.getEq_ID());
            emailData.setDiaRlt(fault.getDia_Rlt());
            DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            emailData.setFaultTime(dtf2.format(fault.getEndTime()));
            if (fault.getTime().equals(fault.getEndTime())) {
                emailData.setIsNewFault(1);
            } else {
                emailData.setIsNewFault(0);
            }
            EmailDatalList.emailDatas.add(emailData);
        }

        if (PublicVars.isPortalWithData == 0 || PublicVars.synFaults == 0)
            return ;

        SyncMessage syncMessage = new SyncMessage();
        syncMessage.setTopic(String.format("fault@%d", fault.getDataServerId()));
        syncMessage.setAction(SyncMessage.ACTION_SAVE);
        // 转为和portal一样的格式。
        syncMessage.setContent(JSON.toJSONString(CommonMethod.fault2Fautl4Sync(fault)));
        //syncMessage.setContent(JSON.toJSONString(fault));
        syncMessage.setCreatetime(Timestamp.from(Instant.now()));

        //
        for (int i = 0; i < sqltrytimes; i++) {
            try {
                syncMessageMapper.insert(syncMessage);
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", "publishFault-syncMessage", ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", "publishFault-syncMessage", ex2.getMessage());
            }
        }
    }
    private void publishFaultall(Faultall faultall) {
        if (PublicVars.isPortalWithData == 0 || PublicVars.synFaults == 0)
            return ;

        SyncMessage syncMessage = new SyncMessage();
        syncMessage.setTopic(String.format("faultall@%d", faultall.getDataServerId()));
        syncMessage.setAction(SyncMessage.ACTION_SAVE);
        syncMessage.setContent(JSON.toJSONString(faultall));
        syncMessage.setCreatetime(Timestamp.from(Instant.now()));

        // syncMessageMapper.insert(syncMessage);
        for (int i = 0; i < sqltrytimes; i++) {
            try {
                syncMessageMapper.insert(syncMessage);
                return;
            } catch (Exception ex) {
                log.error("{} error: {}", "publishFaultall-syncMessage", ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", "publishFaultall-syncMessage", ex2.getMessage());
            }
        }
    }
    private void createWorkbillIfNeed(Fault fault) {
        if (PublicVars.isPortalWithData == 1 && isCreateWorkbill(fault)) {
            try {
                SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
                requestFactory.setConnectTimeout(30000); //设置超时
                requestFactory.setReadTimeout(60000);
                RestTemplate restTemplate = new RestTemplate(requestFactory);
                //RestTemplate restTemplate = new RestTemplate();
                String url = PublicVars.centralPortalApiBaseUrl + "/workbill/fromFault/" + fault.getID();
                log.info(url);
                ResponseEntity<Long> resp = restTemplate.postForEntity(url, null, Long.class);
                if (resp.getStatusCode().isError()) {
                    // throw new RuntimeException(resp.getStatusCode().value() + " " + resp.getStatusCode().getReasonPhrase());
                    log.error("url = {} ", url);
                    log.error("getStatusCode = {} ", resp.getStatusCode().value());
                    log.error("getReasonPhrase = {} ", resp.getStatusCode().getReasonPhrase());
                } else {
                    // 工单号
                    if (resp.getBody() != null && resp.getBody() > 0)
                        fault.setBk2id(resp.getBody());
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    private boolean isCreateWorkbill(Fault fault) {
        // getDialevel 地铁 fault.setDialevel(f1.getDia_Level());
        // return 1 == fault.getDialevel() && !Optional.ofNullable(workbillDao.existsWorkbill(fault.getEq_ID(), fault.getDia_Rlt(), fault.getBk3id())).orElse(false);
        // bk2id 记录 workbillid : 未创建workbill 或者 已经修复
        return 1 == fault.getDialevel()
                && (fault.getBk2id() == 0L || fault.getBk2id() == null || fault.getIsFixed() == 1);
    }
    private void saveFaultall(Fault fault, Boolean isEquipmentFault, int sampleseconds) {
        Faultall faultall = copyFromFault(fault,isEquipmentFault, sampleseconds);

        if (!isEquipmentFault) {
            // 2020-10-02 改为按天记录. Time -- EndTime
            List<Faultall> faultalls = faultallMapper.selectByEqidDiarltTimeday(faultall);
            if (faultalls == null || faultalls.isEmpty()) {

                faultallMapper.insert(faultall);

                publishFaultall(faultall);
            } else {
                Faultall lastfaultall = faultalls.get(0);
                lastfaultall.setTotalTimes(lastfaultall.getTotalTimes() + 1);
                lastfaultall.setPeriod(lastfaultall.getPeriod() + sampleseconds);
                lastfaultall.setEndTime(fault.getEndTime());

                faultallMapper.updateByIdSync(lastfaultall);

                publishFaultall(lastfaultall);
            }
        } else {
            // 修改： 每天只记录一条
            // 2020-12-16 改为按天记录. Time -- EndTime same as above
            int ret = equipmentFaultMapper.update(faultall);
            if (ret == 0) {
                equipmentFaultMapper.insert(faultall);
            }
        }
    }
    private Faultall copyFromFault(Fault fault, Boolean isEquipmentFault, int sampleseconds) {
        Faultall faultall = new Faultall();
        faultall.setDataServerId(fault.getDataServerId());
        faultall.setDataId(fault.getDataId());
        faultall.setStation_ID(fault.getStation_ID());
        faultall.setEq_ID(fault.getEq_ID());
        faultall.setDeptid(fault.getDeptid());
        faultall.setBk3id(fault.getBk3id());
        faultall.setDia_Rlt(fault.getDia_Rlt());
        faultall.setDialevel(fault.getDialevel());
        faultall.setLineid(fault.getLineid());
        faultall.setTime(fault.getTime());
        faultall.setTotalTimes(1);
        faultall.setPeriod(sampleseconds); //PublicVars.sampleseconds
        faultall.setEndTime(fault.getTime());
        faultall.setRemark(fault.getRemark());

        // 新增7大id
        if (!isEquipmentFault) {
            faultall.setEquipmentbrandid(fault.getEquipmentbrandid());
            faultall.setPartbrandid(fault.getPartbrandid());
            faultall.setPartgroupid(fault.getPartgroupid());
            faultall.setPartid(fault.getPartid());
            faultall.setSupplierid(fault.getSupplierid());
            faultall.setSensorid(fault.getSensorid());
            faultall.setSensortype(fault.getSensortype());

            faultall.setBk1(fault.getBk1());
            faultall.setBk2(fault.getBk2());
            faultall.setBk3(fault.getBk3());
            faultall.setBk4(fault.getBk4());
            faultall.setBk5(fault.getBk5());
        }

        LocalDateTime time = fault.getTime();
        faultall.setTimeHour(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), time.getHour(), 0));
        faultall.setTimeDay(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 0, 0));
        faultall.setTimeMonth(LocalDateTime.of(time.getYear(), time.getMonth(), 1, 0, 0));

        return faultall;
    }
    private Faultall copyFromFault4Control56(Fault fault) {
        Faultall faultall = new Faultall();
        faultall.setDataServerId(fault.getDataServerId());
        faultall.setDataId(fault.getDataId());
        faultall.setStation_ID(fault.getStation_ID());
        faultall.setEq_ID(fault.getEq_ID());
        faultall.setDeptid(fault.getDeptid());
        faultall.setBk3id(fault.getBk3id());
        faultall.setDia_Rlt(fault.getDia_Rlt());
        faultall.setDialevel(fault.getDialevel());
        faultall.setLineid(fault.getLineid());
        faultall.setTime(fault.getTime());
        faultall.setTotalTimes(1);
        faultall.setPeriod(PublicVars.sampleseconds);
        faultall.setEndTime(fault.getTime());

        // 新增7大id
        faultall.setEquipmentbrandid(fault.getEquipmentbrandid());
        faultall.setPartbrandid(fault.getPartbrandid());
        faultall.setPartgroupid(fault.getPartgroupid());
        faultall.setPartid(fault.getPartid());
        faultall.setSupplierid(fault.getSupplierid());
        faultall.setSensorid(fault.getSensorid());
        faultall.setSensortype(fault.getSensortype());

        faultall.setBk1(fault.getBk1());
        faultall.setBk2(fault.getBk2());
        faultall.setBk3(fault.getBk3());
        faultall.setBk4(fault.getBk4());
        faultall.setBk5(fault.getBk5());


        LocalDateTime time = fault.getTime();
        faultall.setTimeHour(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), time.getHour(), 0));
        faultall.setTimeDay(LocalDateTime.of(time.getYear(), time.getMonth(), time.getDayOfMonth(), 0, 0));
        faultall.setTimeMonth(LocalDateTime.of(time.getYear(), time.getMonth(), 1, 0, 0));

        return faultall;
    }
    private void faultAndAllAndSyncAndUpdate(Fault lastFault, Fault fault, int sampleseconds, String action){
        int period = lastFault.getPeriod() + sampleseconds; //PublicVars.sampleseconds;

        for (int i = 0; i< sqltrytimes; i++) {
            try {
                faultMapper.updateEndTimeAndPeriodAndTotalTimes(fault.getTime(), period, lastFault.getTotalTimes() + 1, lastFault.getID());
                break;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
        //@Update("update fault set EndTime=#{endTime, jdbcType = TIMESTAMP}, Period=#{period}, TotalTimes=#{totalTimes} where ID=#{id}")
        lastFault.setEndTime(fault.getTime());
        lastFault.setTotalTimes(lastFault.getTotalTimes() + 1);
        lastFault.setPeriod(period);

        publishFault(lastFault);

        fault.setID(lastFault.getID());
        fault.setBk1id(lastFault.getBk1id());
        fault.setBk2id(lastFault.getBk2id());
        fault.setBk3id(lastFault.getBk3id());
        fault.setIsFixed(lastFault.getIsFixed());

        // 这个注意使用 lastFault,但是时间设置为 当前fault
        // 因为很多属性只有 lastFault 才有
        Fault newFault= lastFault;
        newFault.setTime(fault.getTime());
        newFault.setEquipmentbrandid(fault.getEquipmentbrandid());
        newFault.setPartbrandid(fault.getPartbrandid());
        newFault.setPartgroupid(fault.getPartgroupid());
        newFault.setPartid(fault.getPartid());
        newFault.setSupplierid(fault.getSupplierid());
        newFault.setSensorid(fault.getSensorid());
        newFault.setSensortype(fault.getSensortype());
        newFault.setBk1(fault.getBk1());
        saveFaultall(newFault, false, sampleseconds);
        createWorkbillIfNeed(fault);
    }

    public void faultAndAllAndSync56(Fault fault, String action, int sampleseconds) {
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                faultMapper.insert(fault);
                break;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }
        fault.setBk3id(fault.getID());
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                faultMapper.updateBk3id(fault.getBk3id(), fault.getID());
                break;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }

        fault.setIsFixed(0);
        fault.setIsChecked(0);
        fault.setIsReceived(0);
        publishFault(fault);

        // latestfault
        //latestFaultMapper.deleteLatestFaultByStationIdAndEqId(fault.getStation_ID(), fault.getEq_ID());
        fault.setID(fault.getEq_ID() * 100L + 1);
        for (int i = 0; i< sqltrytimes; i++) {
            try {
                LatestSensorStatusData.hasControl56Fault.put(fault.getEq_ID(), 1);
                LatestSensorStatusData.latest56Fault.put(fault.getEq_ID(), fault);
                if (latestFaultMapper.updateLatestFault(fault) <= 0) {
                    latestFaultMapper.insertLatestFault(fault);
                }
                break;
            } catch (Exception ex) {
                log.error("{} error: {}", action, ex.getMessage());
            }
            // 隔2秒再试
            try {
                Thread.sleep(2000);
            }catch (Exception ex2) {
                log.error("{} sleep error: {}", action, ex2.getMessage());
            }
        }

        publishLatestFault(fault);
        latestFaultMapper.deleteLatestFaultByEqIdAndId(fault.getEq_ID(), fault.getEq_ID() * 100L + 2);
        publishDeleteLatestFault(fault.getDataServerId(), fault.getEq_ID(), fault.getEq_ID() * 100L + 2);

        // faultall
        Faultall faultall = copyFromFault4Control56(fault);
        // 2020-10-02 改为按天记录. Time -- EndTime
        //        int ret = faultallMapper.update(faultall);
        //        if (ret == 0) {
        //            faultallMapper.insert(faultall);
        //        }
        List<Faultall> faultalls = faultallMapper.selectByEqidDiarltTimeday(faultall);
        if (faultalls == null || faultalls.isEmpty()) {
            for (int i = 0; i< sqltrytimes; i++) {
                try {
                    faultallMapper.insert(faultall);
                    break;
                } catch (Exception ex) {
                    log.error("{} error: {}", action, ex.getMessage());
                }
                // 隔2秒再试
                try {
                    Thread.sleep(2000);
                }catch (Exception ex2) {
                    log.error("{} sleep error: {}", action, ex2.getMessage());
                }
            }

            publishFaultall(faultall);
        } else {
            Faultall lastfaultall = faultalls.get(0);
            lastfaultall.setTotalTimes(lastfaultall.getTotalTimes() + 1);
            lastfaultall.setPeriod(lastfaultall.getPeriod() + fault.getPeriod());
            lastfaultall.setEndTime(fault.getEndTime());

            for (int i = 0; i< sqltrytimes; i++) {
                try {
                    faultallMapper.updateByIdSync(lastfaultall);
                    break;
                } catch (Exception ex) {
                    log.error("{} error: {}", action, ex.getMessage());
                }
                // 隔2秒再试
                try {
                    Thread.sleep(2000);
                }catch (Exception ex2) {
                    log.error("{} sleep error: {}", action, ex2.getMessage());
                }
            }
            publishFaultall(lastfaultall);
        }
        /*
            //已经配置返回 id
            faultMapper.insert(fault);
            fault.setBk3id(fault.getID());
            faultMapper.updateBk3id(fault.getBk3id(), fault.getID());

            fault.setIsFixed(0);
            fault.setIsChecked(0);
            fault.setIsReceived(0);
            publishFault(fault);

            // latestfault
            //latestFaultMapper.deleteLatestFaultByStationIdAndEqId(fault.getStation_ID(), fault.getEq_ID());
            fault.setID(fault.getEq_ID() * 100L + 1);
            if (latestFaultMapper.updateLatestFault(fault) <= 0) {
                latestFaultMapper.insertLatestFault(fault);
            }
            publishLatestFault(fault);
            latestFaultMapper.deleteLatestFaultByEqIdAndId(fault.getEq_ID(), fault.getEq_ID() * 100L + 2);
            publishDeleteLatestFault(fault.getDataServerId(), fault.getEq_ID(), fault.getEq_ID() * 100L + 2);

            // faultall
            Faultall faultall = copyFromFault4Control56(fault);
            // 2020-10-02 改为按天记录. Time -- EndTime
            //        int ret = faultallMapper.update(faultall);
            //        if (ret == 0) {
            //            faultallMapper.insert(faultall);
            //        }
            List<Faultall> faultalls = faultallMapper.selectByEqidDiarltTimeday(faultall);
            if (faultalls == null || faultalls.isEmpty()) {
                faultallMapper.insert(faultall);
                publishFaultall(faultall);
            } else {
                Faultall lastfaultall = faultalls.get(0);
                lastfaultall.setTotalTimes(lastfaultall.getTotalTimes() + 1);
                lastfaultall.setPeriod(lastfaultall.getPeriod() + fault.getPeriod());
                lastfaultall.setEndTime(fault.getEndTime());
                faultallMapper.updateByIdSync(lastfaultall);
                publishFaultall(lastfaultall);
            }
         */
    }
    private void publishLatestFault(Fault fault) {
        return ; // 目前正常情况也有0000，太多了，不同步suiteng

//        if (PublicVars.isPortalWithData == 0 || PublicVars.synFaults == 0)
//            return ;
//
//        SyncMessage syncMessage = new SyncMessage();
//        syncMessage.setTopic(String.format("latestfault@%d", fault.getDataServerId()));
//        syncMessage.setAction(SyncMessage.ACTION_SAVE);
//        //syncMessage.setContent(JSON.toJSONString(fault));
//        syncMessage.setContent(JSON.toJSONString(CommonMethod.fault2Fautl4Sync(fault)));
//        syncMessage.setCreatetime(Timestamp.from(Instant.now()));
//        syncMessageMapper.insert(syncMessage);
    }
    private void publishDeleteLatestFault(int dataserverid, int equipmentid, long beginid) {
        return; // 目前正常情况也有0000，太多了，不同步suiteng

//        if (PublicVars.synFaults == 0)
//            return ;
//
//        SyncMessage syncMessage = new SyncMessage();
//        syncMessage.setTopic(String.format("deletelatestfault@%d", dataserverid));
//        syncMessage.setAction(SyncMessage.ACTION_DELETE);
//        syncMessage.setContent(String.format("%d,%d", equipmentid, beginid));
//        syncMessage.setCreatetime(Timestamp.from(Instant.now()));
//        syncMessageMapper.insert(syncMessage);
    }

    // 这个暂时没有用到，先不增加判断sqltimes了
    public void fault4ElevatorAndSync(Fault fault, String action, int sampleseconds) {
        //已经配置返回 id
        faultMapper.insert(fault);
        fault.setBk3id(fault.getID());
        faultMapper.updateBk3id(fault.getBk3id(),fault.getID());

        fault.setIsFixed(0);
        fault.setIsChecked(0);
        fault.setIsReceived(0);
        publishFault(fault);

        // latestfault
        //latestFaultMapper.deleteLatestFaultByStationIdAndEqId(fault.getStation_ID(), fault.getEq_ID());
        fault.setID(fault.getEq_ID()*100L + 1);
        if (latestFaultMapper.updateLatestFault(fault) <= 0) {
            latestFaultMapper.insertLatestFault(fault);
        }
        publishLatestFault(fault);
        latestFaultMapper.deleteLatestFaultByEqIdAndId(fault.getEq_ID(),fault.getEq_ID() * 100L + 2);
        publishDeleteLatestFault(fault.getDataServerId(), fault.getEq_ID(),fault.getEq_ID() * 100L + 2);

        // faultall
        Faultall faultall = copyFromFault4Control56(fault);
        // 2020-10-02 改为按天记录. Time -- EndTime
        //        int ret = faultallMapper.update(faultall);
        //        if (ret == 0) {
        //            faultallMapper.insert(faultall);
        //        }
        List<Faultall> faultalls = faultallMapper.selectByEqidDiarltTimeday(faultall);
        if (faultalls == null || faultalls.isEmpty()) {
            faultallMapper.insert(faultall);
            publishFaultall(faultall);
        } else {
            Faultall lastfaultall = faultalls.get(0);
            lastfaultall.setTotalTimes(lastfaultall.getTotalTimes() + 1);
            lastfaultall.setPeriod(lastfaultall.getPeriod() + fault.getPeriod());
            lastfaultall.setEndTime(fault.getEndTime());
            faultallMapper.updateByIdSync(lastfaultall);
            publishFaultall(lastfaultall);
        }
    }

    public void uploadConfigs(String mapStr) {
        Map<String, String> reqBody = GsonUtils.getGson().fromJson(mapStr, new TypeToken<Map<String, String>>() {
        }.getType());

        List<ClientConfigparamsVersion> clientConfigsVersions;
        List<Client_Configs> client_configs;
        List<Client_Params> client_params;
        List<Client_Ai_Params> client_ai_params;
        List<Client_Vib_Params> client_vib_params;
        List<Client_Public_Params> client_public_params;
        List<Client_Dm_Params> client_dm_params;
        String sLineid = reqBody.get("lineid");
        String sStationid = reqBody.get("stationid");
        String sEquipmentid = reqBody.get("equipmentid");
        String version = reqBody.get("version");
        if (version == null)
            version="no-version";
        String datatype = reqBody.get("datatype");
        if (sLineid==null || sLineid.isEmpty() || sStationid==null || sStationid.isEmpty() || sEquipmentid==null || sEquipmentid.isEmpty() || datatype == null || datatype.isEmpty()) {
            log.error("上传信息缺少：lineid / stationid / equipmentid / datatype");
            return;
        }
        Integer lineid=Integer.parseInt(sLineid);
        Integer stationid=Integer.parseInt(sStationid);
        Integer equipmentid=Integer.parseInt(sEquipmentid);
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String nowDateTime = dtf2.format(LocalDateTime.now());

        try {
            versionInfoDao.deleteVerionInfo(equipmentid);
            versionInfoDao.insertVerionInfo(lineid,stationid,equipmentid,version);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        // log.error(response);
        if (reqBody.get("ClientConfigsVersion") != null) {
            clientConfigsVersions = GsonUtils.getGson().fromJson(reqBody.get("ClientConfigsVersion"), new TypeToken<List<ClientConfigparamsVersion>>() {
            }.getType());

            if (clientConfigsVersions != null && clientConfigsVersions.isEmpty() == false) {
                clientConfigparamsVersionUploadDao.deleteByEquipmentId(equipmentid);
                clientConfigsVersions.forEach(item -> {
                    // bk1 记录时间
                    item.setBk1(nowDateTime);
                    clientConfigparamsVersionUploadDao.insert(item);
                });
            }
        }
        if (reqBody.get("ClientConfigs") != null) {
            client_configs = GsonUtils.getGson().fromJson(reqBody.get("ClientConfigs"), new TypeToken<List<Client_Configs>>() {
            }.getType());

            if (client_configs != null && client_configs.isEmpty() == false) {
                // 如果存在，更新。否则insert。原有的保留
                clientConfigsUploadDao.deleteByEquipmentIdDataType(equipmentid, client_configs.get(0).getData_type());
                client_configs.forEach(item -> {
                    Client_Configs_Upload itemUpload = new Client_Configs_Upload();
                    itemUpload.setLineid(lineid);
                    itemUpload.setStationid(stationid);
                    itemUpload.setEquipmentid(equipmentid);
                    itemUpload.setConfig_name(item.getConfig_name());
                    itemUpload.setConfig_type(item.getConfig_type());
                    itemUpload.setConfig_value(item.getConfig_value());
                    itemUpload.setConfig_can_modify(item.getConfig_can_modify());
                    itemUpload.setRemark(nowDateTime);// 记录当前时间
                    itemUpload.setData_type(datatype);
                    clientConfigsUploadDao.insert(itemUpload);
                });
                logTheUploadTime("Config", lineid, stationid, equipmentid);
            }
        }
        if (reqBody.get("ClientParams") != null) {
            client_params = GsonUtils.getGson().fromJson(reqBody.get("ClientParams"), new TypeToken<List<Client_Params>>() {
            }.getType());

            if (client_params != null && client_params.isEmpty() == false) {
                clientParamsUploadDao.deleteByEquipmentIdDataType(equipmentid);
                client_params.forEach(item -> {
                    // 这个表没有记录时间字段
                    // DONGWEI: 工控机 client_params 不能 有 lineid
                    item.setLineid(lineid);
                    clientParamsUploadDao.insert(item);
                });
                logTheUploadTime("Params", lineid, stationid, equipmentid);
            }
        }
        if (reqBody.get("ClientAiParams") != null) {
            client_ai_params = GsonUtils.getGson().fromJson(reqBody.get("ClientAiParams"), new TypeToken<List<Client_Ai_Params>>() {
            }.getType());

            if (client_ai_params != null && client_ai_params.isEmpty() == false) {
                clientAiParamsUploadDao.deleteByEquipmentId(equipmentid);
                client_ai_params.forEach( item -> {
                    // 这个表没有记录时间字段
                    // DONGWEI: 工控机 client_ai_params 不能 有 lineid
                    item.setLineid(lineid);
                    // 旧版本兼容
                    /*
                        alter table client_ai_params add  `RMS_MIN` decimal(12,5) DEFAULT '-20' ;
                        alter table client_ai_params add  `RMS_MAX` decimal(12,5) DEFAULT '80.00000' ;
                        alter table client_ai_params add  `Refer_ChanelNum` int(11) NOT NULL DEFAULT '-100' ;
                        alter table client_ai_params add  `Refer_History` decimal(12,5) DEFAULT '-100' ;
                        alter table client_ai_params add  `Refer_Value` decimal(12,5) DEFAULT '-100' ;
                        alter table client_ai_params add  `Bk3` decimal(12,5) DEFAULT NULL ;
                        alter table client_ai_params add  `Bk4` varchar(100) DEFAULT NULL ;
                        alter table client_ai_params add  `BD_State` int(11) NOT NULL DEFAULT 0;
                        alter table client_ai_params add  `BD_Value1` decimal(12,5) DEFAULT 0.00000;
                        alter table client_ai_params add  `BD_Value2` decimal(12,5) DEFAULT 0.00000;
                        alter table client_ai_params add  `BD_Value_Dif` decimal(12,5) DEFAULT 0.00000;
                        alter table client_ai_params add  `BD_Value_Trigger` decimal(12,5) DEFAULT 3.00000;
                        alter table client_ai_params add  `BD_Value_DifAdd` decimal(12,5) DEFAULT 0.00000;
                    */
                    if (item.getRMS_MIN() == null) item.setRMS_MIN(new BigDecimal("-20"));
                    if (item.getRMS_MAX() == null) item.setRMS_MAX(new BigDecimal("80"));
                    if (item.getRefer_ChanelNum() == null) item.setRefer_ChanelNum(-100);
                    if (item.getRefer_History() == null) item.setRefer_History(new BigDecimal("-100"));
                    if (item.getRefer_Value() == null) item.setRefer_Value(new BigDecimal("-100"));
                    if (item.getBD_State() == null) item.setBD_State(0);
                    if (item.getBD_Value1() == null) item.setBD_Value1(new BigDecimal("0.00000"));
                    if (item.getBD_Value2() == null) item.setBD_Value2(new BigDecimal("0.00000"));
                    if (item.getBD_Value_Dif() == null) item.setBD_Value_Dif(new BigDecimal("0.00000"));
                    if (item.getBD_Value_Trigger() == null) item.setBD_Value_Trigger(new BigDecimal("3.00000"));
                    if (item.getBD_Value_DifAdd() == null) item.setBD_Value_DifAdd(new BigDecimal("0.00000"));
                    clientAiParamsUploadDao.insert(item);
                });
                logTheUploadTime("Ai", lineid, stationid, equipmentid);
            }
        }
        if (reqBody.get("ClientVibParams") != null) {
            client_vib_params = GsonUtils.getGson().fromJson(reqBody.get("ClientVibParams"), new TypeToken<List<Client_Vib_Params>>() {
            }.getType());

            if (client_vib_params != null && client_vib_params.isEmpty() == false) {
                clientVibParamsUploadDao.deleteByEquipmentId(equipmentid);
                client_vib_params.forEach(item -> {
                    // 这个表没有记录时间字段
                    // DONGWEI: 工控机 client_vib_params 不能 有 lineid
                    item.setLineid(lineid);
                    // 旧版本兼容
                    /*
                        alter table client_vib_params add  `RMS_MIN` decimal(12,5) DEFAULT '0';
                        alter table client_vib_params add  `RMS_MAX` decimal(12,5) DEFAULT '12';
                        alter table client_vib_params add  `Refer_ChanelNum` int(11) NOT NULL DEFAULT '-100';
                        alter table client_vib_params add  `Refer_History` decimal(12,5) DEFAULT '1.00000';
                        alter table client_vib_params add  `Refer_Value` decimal(12,5) DEFAULT '-100.00000';
                     */
                    if (item.getRMS_MIN() == null) item.setRMS_MIN(new BigDecimal("0"));
                    if (item.getRMS_MAX() == null) item.setRMS_MAX(new BigDecimal("12"));
                    if (item.getRefer_ChanelNum() == null) item.setRefer_ChanelNum(-100);
                    if (item.getRefer_History() == null) item.setRefer_History(new BigDecimal("1.00000"));
                    if (item.getRefer_Value() == null) item.setRefer_Value(new BigDecimal("-100.00000"));
                    clientVibParamsUploadDao.insert(item);
                });
                logTheUploadTime("Vib", lineid, stationid, equipmentid);
            }
        }
        if (reqBody.get("ClientPublicParams") != null) {
            client_public_params = GsonUtils.getGson().fromJson(reqBody.get("ClientPublicParams"), new TypeToken<List<Client_Public_Params>>() {
            }.getType());

            if (client_public_params == null || client_public_params.isEmpty()) {
                return;
            }
            clientPublicParamsUploadDao.deleteByEquipmentId(equipmentid);
            client_public_params.forEach( item -> {
                // 这个表没有记录时间字段
                // DONGWEI: 工控机 client_public_params 不能 有 lineid
                item.setLineid(lineid);
                clientPublicParamsUploadDao.insert(item);
                if (item.getEquipmentid() != null && item.getMap_Current() != null) {
                    PublicVars.mapCurrent.remove(item.getEquipmentid());
                }
            });
            logTheUploadTime("Public", lineid, stationid, equipmentid);
        }
        if (reqBody.get("ClientDmParams") != null) {
            client_dm_params = GsonUtils.getGson().fromJson(reqBody.get("ClientDmParams"), new TypeToken<List<Client_Dm_Params>>() {
            }.getType());

            if (client_dm_params != null && client_dm_params.isEmpty() == false) {
                clientDmParamsUploadDao.deleteByEquipmentId(equipmentid);
                client_dm_params.forEach( item -> {
                    // 这个表没有记录时间字段
                    // DONGWEI: 工控机 client_dm_params 不能 有 lineid
                    item.setLineid(lineid);
                    clientDmParamsUploadDao.insert(item);
                });
                logTheUploadTime("Dm", lineid, stationid, equipmentid);
            }
        }
    }
    //记录时间
    private void logTheUploadTime(String datatype, Integer lineid, Integer stationid, Integer equipmentid) {
        if (PublicVars.isPortalWithData != 1) {
            return;
        }
        Client_AiVibPublicDm_UploadTime client_aiVibPublicDm_uploadTime = new Client_AiVibPublicDm_UploadTime();
        client_aiVibPublicDm_uploadTime.setDatatype(datatype);
        client_aiVibPublicDm_uploadTime.setLineid(lineid);
        client_aiVibPublicDm_uploadTime.setStationid(stationid);
        client_aiVibPublicDm_uploadTime.setEquipmentid(equipmentid);
        client_aiVibPublicDm_uploadTime.setMakedate(Timestamp.valueOf(LocalDateTime.now()));
        if (clientAiVibPublicDmUploadTimeDao.updateByEquipmentIdDataType(client_aiVibPublicDm_uploadTime) <= 0) {
            clientAiVibPublicDmUploadTimeDao.insert(client_aiVibPublicDm_uploadTime);
        }
    }
}